#pragma once

#ifdef WIN32
#include <windows.h>
void sleep(int ms) {
    Sleep(ms);
}
#else
#include <unistd.h>
void sleep(int ms) {
    usleep(ms * 1000);
}
#endif

class Component
{
public:
    virtual void clk() = 0;
};

class Timer
{
public :
    Timer(int interval, std::function<void(void)> expire);
    void start();
    void pause();
private:
    std::function<void(void)> expire;
    void run();
    int interval;
    bool state;
};

class Divider :Component
{
public:
    Divider(uint8_t step, std::function<void(void)> f);
    virtual void clk();
    std::function<void(void)> f;
private:
    uint8_t counter;
    uint8_t step;
};

class SimMcu :Component
{
public:
    uint8_t rom[4096];
    uint8_t ram[1024];
    uint16_t pc;
    uint16_t ir;
    uint8_t acc;
    uint8_t *r;
    uint8_t psw;
    Divider divider;
    Timer timer;
    
    SimMcu();
    void start();
    void pause();
    virtual void clk();
    virtual void clkin();
private:
    static std::function<uint16_t(SimMcu&)> Insts[256];
    void createInsts();
    uint16_t id(uint8_t inst);
};

class HexParser
{
public:
    static void parse(uint8_t* dest, const char* filename);
    static int atoi(char* input, int len, uint8_t p);
};